package com.dmwork.service.message.mq.receiver;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dmwork.common.base.result.ExceptionUtils;
import com.dmwork.common.base.util.StringUtils;
import com.dmwork.service.message.entity.*;
import com.dmwork.service.message.feign.CustomerFeignService;
import com.dmwork.service.message.service.*;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Slf4j
@Transactional
@Component
public class MessageReceiver {

    @Autowired
    private FeedFollowMessageService feedFollowMessageService;
    @Autowired
    private CustomerFeignService customerFeignService;
    @Autowired
    private CommentMessageService commentMessageService;
    @Autowired
    private CommentLikeMessageService commentLikeMessageService;
    @Autowired
    private SystemMessageService systemMessageService;

    //系统通知内容
    @Value("${system-message-template.admin-remove-work-system-message}")
    private String adminRemoveWorkSystemMessage; //管理员下架用户的作品的系统通知内容模板


    /**
     * 为被回复的用户创建一条消息
     *
     * @param message
     * @param channel
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-message-receive.x-dead-letter-exchange}"),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-message-receive.x-dead-letter-routing-key}")
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-comment-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onCommentMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            Integer flag = (Integer) message.getHeaders().get("flag");
            if (flag == 1) {
                CommentMessage commentMessage = new CommentMessage();
                commentMessage.setCustomerId((String) payload.get("customerId"));
                commentMessage.setCommentId((String) payload.get("commentId"));
                commentMessage.setType((Integer) payload.get("type"));
                commentMessageService.save(commentMessage);
            } else if (flag == 0) {
                QueryWrapper<CommentMessage> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("customer_id", (String) payload.get("customerId"))
                        .eq("comment_id", (String) payload.get("commentId"));
                commentMessageService.remove(queryWrapper);
            }
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * flag==1：为被点赞的评论所属用户创建一条消息
     * flag==0：说明是取消点赞的操作，则删除原来的点赞消息
     *
     * @param message
     * @param channel
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-message-receive.x-dead-letter-exchange}"),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-message-receive.x-dead-letter-routing-key}")
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onCommentLikeMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            Integer flag = (Integer) message.getHeaders().get("flag");
            log.info(flag+"");
            if (flag == 1) { //如果flag==1，则是创建一条点赞消息
                CommentLikeMessage commentLikeMessage = new CommentLikeMessage();
                commentLikeMessage.setCustomerId((String) payload.get("customerId"));
                commentLikeMessage.setLikeId((String) payload.get("likeId"));
                commentLikeMessage.setType((Integer) payload.get("type"));
                commentLikeMessageService.save(commentLikeMessage);
            } else if (flag == 0) { //如果flag==0，说明是取消点赞的操作，则删除原来的点赞消息
                QueryWrapper<CommentLikeMessage> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("customer_id", (String) payload.get("customerId"))
                        .eq("like_id", (String) payload.get("likeId"));
                commentLikeMessageService.remove(queryWrapper);
            }
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 当用户发送动态时，为所有关注该用户的粉丝创建一条新动态消息通知
     *
     * @param message
     * @param channel
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-message-receive.x-dead-letter-exchange}"
                                    ),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-message-receive.x-dead-letter-routing-key}"
                                    )
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-feed-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onFeedMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            String feedId = (String) payload.get("feedId"); //动态id
            String customerId = (String) payload.get("customerId");//动态发送者id
            List<String> followerIdList = customerFeignService.getFollowerIdList(customerId); //获取该用户所有粉丝的id列表
            List<FeedFollowMessage> feedFollowMessageList = new LinkedList<>();
            for (String followerId : followerIdList) {
                FeedFollowMessage feedFollowMessage = new FeedFollowMessage();
                feedFollowMessage.setFeedId(feedId);
                feedFollowMessage.setCustomerId(customerId);
                feedFollowMessage.setFollowerId(followerId);
                feedFollowMessageList.add(feedFollowMessage);
            }
            feedFollowMessageService.saveBatch(feedFollowMessageList);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //事务回滚
        }
    }


    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-view-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-view-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-view-message-receive.x-dead-letter-exchange}"
                                    ),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-feed-view-message-receive.x-dead-letter-routing-key}"
                                    )
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-feed-view-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onFeedMessageReadReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            log.info(message.getPayload().toString());
            Map<String, Object> payload = message.getPayload();
            String customerId = (String) payload.get("customerId");
            feedFollowMessageService.setReadFeedByCustomerId(customerId);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 将指定用户的评论消息设置为已读
     *
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-read-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-read-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-read-message-receive.x-dead-letter-exchange}"
                                    ),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-read-message-receive.x-dead-letter-routing-key}"
                                    )
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-comment-read-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onCommentReadMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            String customerId = (String) payload.get("customerId");
            CommentMessage commentMessage = new CommentMessage();
            commentMessage.setReadStatus(1);
            commentMessageService.update(commentMessage, new QueryWrapper<CommentMessage>().eq("customer_id", customerId).eq("read_status", 0));
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 处理评论消息已读
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-read-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-read-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-read-message-receive.x-dead-letter-exchange}"
                                    ),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-read-message-receive.x-dead-letter-routing-key}"
                                    )
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-comment-like-read-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onCommentLikeReadMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            String customerId = (String) payload.get("customerId");
            CommentLikeMessage commentLikeMessage = new CommentLikeMessage();
            commentLikeMessage.setReadStatus(1);
            commentLikeMessageService.update(commentLikeMessage, new QueryWrapper<CommentLikeMessage>()
                    .eq("customer_id", customerId)
                    .eq("read_status", 0));
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 为作品被系统下架的用户创建通知消息
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-admin-remove-work-system-message-receive.queue.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.on-admin-remove-work-system-message-receive.queue.durable}",
                            arguments = {
                                    @Argument(
                                            name = "x-dead-letter-exchange",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-admin-remove-work-system-message-receive.x-dead-letter-exchange}"
                                    ),
                                    @Argument(
                                            name = "x-dead-letter-routing-key",
                                            value = "${spring.rabbitmq.custom.receiver.message-receiver.on-admin-remove-work-system-message-receive.x-dead-letter-routing-key}"
                                    )
                            }
                    ),
                    exchange = @Exchange(
                            value = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.name}",
                            durable = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.durable}",
                            type = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.type}",
                            ignoreDeclarationExceptions = "${spring.rabbitmq.custom.receiver.message-receiver.exchange.ignore-declaration-exceptions}"
                    ),
                    key = {"${spring.rabbitmq.custom.receiver.message-receiver.on-admin-remove-work-system-message-receive.key}"}
            )
    })
    @RabbitHandler
    public void onAdminRemoveWorkSystemMessageReceive(Message<Map<String, Object>> message, Channel channel) throws IOException {
        try {
            Map<String, Object> payload = message.getPayload();
            String customerId= (String) payload.get("customerId");
            String title= (String) payload.get("title");
            String content = StringUtils.templateContentPadding(adminRemoveWorkSystemMessage, '%', title);
            SystemMessage systemMessage = new SystemMessage();
            systemMessage.setCustomerId(customerId);
            systemMessage.setContent(content);
            systemMessageService.save(systemMessage);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
            long deliveryTag = (long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
            channel.basicNack(deliveryTag, false, false);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

    }

}
